import ReconnectingWebSocket from "./reconnect-websocket"
import {SM2} from "gm-crypto"
import {formatDate} from "element-ui/src/utils/date-util";

console.log(SM2.generateKeyPair())

var vars = window._ws || {
    readyContexts:[],
    handlers: {
    },
    promise: {
    },
    publicKey: "",
    privateKey: "",
    ws: (function () {
        var ws = new ReconnectingWebSocket(`ws://${location.host}/api/socket`)
        // ws.binaryType = "arraybuffer";
        // ws.onopen = function () {
            // (vars.handlers.open || []).forEach(e => e());
        // }
        ws.onmessage = function(e){
            var obj = JSON.parse(e.data)
            console.log(obj)
            if(obj.event === 'RESP_PUBLIC_KEY'){
                obj = JSON.parse(obj.data)
                vars.publicKey = obj.pub
                vars.privateKey = obj.pri
                console.log("public key is", vars.publicKey, vars.privateKey)
                vars.readyContexts.forEach(e => {
                    console.log(e)
                    _send(e.event, e.data, e.requestId, e.reject)
                })
                this.readyContexts = []
                return
            }
            if(obj.event === 'RESP_AUTH_FAILED'){
                $vue.$message.error("请先获取系统授权再进行操作")
                return;
            }
            if(obj.data){
                $vue.$emit("server-log", `【${formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")}】【回复密文】${obj.data}`)
            }
            var respId = obj.responseId
            if(vars.promise[respId]){
                var fn = vars.promise[respId]
                delete vars.promise[respId]
                //解密
                var de = SM2.decrypt(obj.data, vars.privateKey,{
                    inputEncoding: "hex",
                    outputEncoding:"utf8"
                })
                console.log("de is", de)
                $vue.$emit("server-log", `【${formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")}】【回复解密】${de}`)
                fn(JSON.parse(de))
            }
        }
        return ws
    })()
}

function guid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function _send(event, data, reqId, reject) {
    //opened
    var str = JSON.stringify({
        event,
        data,
        requestId: reqId
    })
    if(!vars.publicKey){
        alert("failed!")
        return
    }
    $vue.$emit("client-log", `【${formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")}】【请求原文】${str}`)
    var crypt = SM2.encrypt(JSON.stringify(data), vars.publicKey, {
        inputEncoding: "utf8",
        outputEncoding: "hex"
    })
    // var res = SM2.decrypt(crypt, vars.privateKey,{
    //     outputEncoding:"utf8"
    // })
    // console.log(crypt, res)
    var sendData = JSON.stringify({
        event,
        data: crypt,
        requestId: reqId
    })
    $vue.$emit("client-log", `【${formatDate(new Date(), "yyyy-MM-dd HH:mm:ss")}】【请求密文】${crypt}`)
    vars.ws.send(sendData)
    // window.$vue.$emit("client-log", "123312")
    //request timeout
    setTimeout(function () {
        if(vars.promise[reqId]){
            delete vars.promise[reqId]
            reject()
        }
    },30000)
}

var exp = {
    on: function (event, handler) {
        vars.handlers[event] = vars.handlers[event] || []
        vars.handlers[event].push(handler)
    },
    remove: function (event, handler) {
        vars.handlers[event] = (vars.handlers[event] || []).filter(e => e !== handler)
    },
    async send(event, data = {}, reqId = null){
        return new Promise(function (resolve, reject) {
            var reqId = guid()
            vars.promise[reqId] = resolve
            if(vars.ws.readyState === 1 && vars.publicKey){
                _send(event, data, reqId, reject)
            } else {
                vars.readyContexts.push({
                    event,
                    data,
                    requestId: reqId,
                    reject
                })
            }
        });
    }
}

export default exp
